﻿using G.Model;

namespace G.Runtime
{
    public class GameClickEventArgs
    {
        public GameLocation location;
        public GameElement element;
        public bool handled;
    }
        
    public class GameEndEventArgs
    {
        public bool win;
    }
    
    public class GameSpace 
    {
        public delegate void EndHandler(GameEndEventArgs args);
        public delegate void ClickHandler(GameClickEventArgs args);
        public event EndHandler End;
        public event ClickHandler Click;
        
        private readonly GameSpaceDef _GameDef;
        private readonly GameElements _Elements;
        private readonly GamePlayers _Players;
        private readonly GameController _GameController;
        private readonly GameGlobals _GameGlobals;
        private readonly GameTasks _GameTasks;
        
        private bool _Started;
        
        public GameSpace(GameSpaceDef pGameDef)
        {
            _GameDef = pGameDef;
            _Elements = new GameElements(pGameDef.GameElementDefs, this);
            _Players = new GamePlayers(pGameDef.GamePlayerDefs, this);
            _GameGlobals = new GameGlobals(pGameDef.GlobalDef, this);
            _GameTasks = new GameTasks(pGameDef.GameTaskDefs, this);
            _GameController = new StandardGameController(this);
            
            foreach (GamePlayerDef def in pGameDef.GamePlayerDefs)
            {
                if (def.Name == "Nothing")
                {
                    continue;
                }
                
                GamePlayer v = new GamePlayer(def, this);
                if (!_Players.Contains(v.Name))
                {
                    _Players.Add(v);
                }
            }

            foreach (GameElementDef def in pGameDef.GameElementDefs)
            {
                GameElement v = new GameElement(def, this);
                if (!this.Elements.Contains(v))
                {
                    this.Elements.Add(v);
                }

                GamePlayer player = _Players.Get(v.Player);
                if (player != null)
                {
                    player.GameValues.Add(v.GameValues);
                }

            }
            
            foreach (GameTaskDef taskDef in pGameDef.GameTaskDefs)
            {
                GameTask task = new GameTask(taskDef, this);
                _GameTasks.Add(taskDef);
            }
        }
        
        public void Start()
        {
            _GameController.Start();
            _Started = true;
        }

        public bool Started
        {
            get { return _Started; }
        }
        
        public GameSpaceDef Def
        {
            get { return _GameDef; }
        }

        public GameGlobals Globals
        {
            get { return _GameGlobals; }
        }

        public GameElements Elements
        {
            get { return _Elements; }
        }

        public GamePlayers Players
        {
            get { return _Players; }
        }

        public GameTasks Tasks
        {
            get { return _GameTasks; }
        }
        
        public GameController Controller
        {
            get { return _GameController; }
        }
        
        public void FireEndEvent(GameEndEventArgs args)
        {
            if (End != null)
            {
                End(args);
            }
        }

        public GameClickEventArgs FireClickEvent(GameLocation location,
                                                 GameElement element)
        {
            GameClickEventArgs args = new GameClickEventArgs();
            if (this.Click != null)
            {
                args.location = location;
                args.element = element;
                this.Click(args);
            }
            
            return args;
        }
        
    }
}
